using System;
using System.Globalization;
#if !NETFX_CORE && !UNIVERSAL
using System.Windows.Data;
using System.Windows.Markup;
#else
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Markup;
#endif
namespace Prometheus.Binding.ReadOnly.BaseConverters
{
    /// <summary>
    /// Converter that can contain another converter in it self
    /// </summary>
    [ContentProperty(
#if NETFX_CORE || UNIVERSAL
Name = 
#endif
        "Converter")]
    public abstract class proChainConverter : IValueConverter
    {
        /// <summary>
        /// Inheritor can override this property and provide the type of value, that is going from inner converter
        /// If null - targetType is used
        /// Null is default
        /// </summary>
        public virtual Type ThisType
        {
            get { return null; }
        }

        /// <summary>
        /// Inner converter
        /// </summary>
        public IValueConverter Converter { get; set; }

        #region IValueConverter Members

        /// <summary>
        /// IValueConverter.Convert code
        /// </summary>
        object IValueConverter.Convert(object value, Type targetType, object parameter,  
#if NETFX_CORE
            string language
#else
            CultureInfo culture
#endif
            )
        {
            if (Converter != null) value = Converter.Convert(value, ThisType ?? targetType, parameter, 
#if NETFX_CORE
            language
#else
            culture
#endif
                );

            return Convert(value, targetType, parameter, 
#if NETFX_CORE
            null
#else
            culture
#endif
            );
        }

        /// <summary>
        /// IValueConverter.ConvertBack code
        /// </summary>
        object IValueConverter.ConvertBack(object value, Type targetType, object parameter,
#if NETFX_CORE
 string language
#else
            CultureInfo culture
#endif
            )
        {
            if (Converter == null) return ConvertBack(value, targetType, parameter,
#if NETFX_CORE
 null
#else
            culture
#endif
                );

            Type tarType = null;
            var chainConverter = Converter as proChainConverter;
            if (chainConverter != null)
                tarType = chainConverter.ThisType;

            object thisResult = ConvertBack(value, tarType ?? targetType, parameter,
#if NETFX_CORE
 null
#else
            culture
#endif
                );
            return Converter.ConvertBack(thisResult, targetType, parameter,
#if NETFX_CORE
 language
#else
            culture
#endif
                );
        }

        #endregion

        /// <summary>
        /// Inheritor must implement converting
        /// </summary>
        /// <param name="value">Source's value</param>
        /// <param name="targetType">The type which is expected of return value</param>
        /// <param name="parameter">Parameter from binding</param>
        /// <param name="culture">Culture passed from binding</param>
        /// <returns>Converted value</returns>
        public abstract object Convert(object value, Type targetType, object parameter, CultureInfo culture);

        /// <summary>
        /// Inheritor must implement back-converting
        /// </summary>
        /// <param name="value">Target's value</param>
        /// <param name="targetType">source value type</param>
        /// <param name="parameter">Parameter from binding</param>
        /// <param name="culture">Culture from binding</param>
        /// <returns>Back converted value</returns>
        public abstract object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
    }
}